Conversation
…, SAM homegrown-otto skill, Access selfhost wiring
Selfhost can disable OpenRouter ZDR for first-party Anthropic, and SAM can report HomeGrown OTTO queue plus agency-board pixel status without claiming live applies. Co-authored-by: Cursor <cursoragent@cursor.com>
Port analysis and care recipes into OpenSEO. Refuse Ads, Cloud Stacks, paid PR, and auto-publish. Fix tsc so selfhost deploy can finish.
get_agency_score_inputs now reports GSC/GA4 connection state, GBP native-gap status, and last-28-day Search Console site totals (per-day rows summed, impression-weighted position — the default ["query"] dimension's first row is the top query, not totals). Null means not measured, never an invented zero: unmapped, empty, errored, and non-finite paths all return null; a genuinely measured zero stays zero. Sam's system prompt carries the niceseo-pillars law verbatim. Reviewed: Grok 4.6 (cross-family one-off, Jon-authorized 2026-08-31 — both Kimi reviewer lanes quota-blocked), round 2 APPROVE. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Set via API 2026-08-31; pinned here so a redeploy doesn't silently reset the app to the 24h default. Reviewed: Grok 4.6 (cross-family one-off, Jon-authorized), APPROVE. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kimi-reviewed (1 repair round, APPROVE). Two tools wrapping the existing ai-search services: get_ai_brand_visibility (LLM Mentions, SoV, cited sources) and explore_ai_prompt (max 2 models). Cache-first, credits noted in descriptions, absent metrics say 'not measured', registered for MCP and Sam. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kimi-reviewed (APPROVE, round 1). wrapLanguageModel middleware adds cache breakpoints (last tool, last system, last message; <=4) for anthropic/ model ids only; OPENROUTER_PROMPT_CACHE=false or any other model = byte-identical identity. Per-step cache counters logged as [sam] cache. Expected 75-90% input-cost cut on multi-step turns. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…re inputs Lead-authored (Do-Not-Route: schema). sam_loops + sam_loop_runs (one in-flight run per loop enforced at the DB), ai_visibility_configs/prompts/runs (prompt-set versioned baselines), and gscTopQueries (top-25 real GSC queries by clicks) in the agency score inputs. Migration generation happens in the loops build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kimi-reviewed (1 repair round, APPROVE — zero findings above LOW). A loop = skill|custom prompt + cadence + project. Cron claims due loops (DB-enforced single in-flight run), SamLoopWorkflow runs Sam headlessly (step cap 24) with a FAIL-CLOSED tool allowlist: free readers + propose_homegrown_otto_fixes only — new tools are blocked by default. Plain-English run reports, honest proposalsQueued (successful proposals only), six seeded default loops per project, loops UI page, read-only MCP tools, D1+PG migrations with parity test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…posal From the mined SA playbook catalog. Double-reviewed (Kimi + second seat), one repair round, APPROVE: only striking-distance auto-seeds as a loop template — the three parameterized skills are on-demand (a headless loop cannot supply a prospect domain / city+service / competitor set, and must never improvise one). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ft handoff, starter-loop seeding Four Session-5 papercuts: manual trigger no longer skips the scheduled run (future nextRunAt untouched; due/missing/corrupt re-anchors from now); mission card click scrolls the report into view once per selection; Ask-Sam draft is read+cleared by the chat composer on mount (prefill, no auto-send); empty loops list gets a one-click idempotent starter-loops seed (real unique-index test). Built by Cursor auto in a detached worktree off 153a51f; Kimi review round 1 FIX-THEN-COMMIT (mock-only idempotence test, scroll hijack, draft-key linger, unparsable-anchor strand), round 2 APPROVE. tsc clean; vitest 1200/1200 in this tree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
GET /api/internal/agency-loop-reports — read-only, bearer-gated with the existing AGENCY_SCORE_EXPORT_TOKEN (deliberate reuse, commented): completed and failed sam_loop_runs joined to loop + project, inclusive lexical finishedAt cursor (since required, ms-ISO validated), limit clamped 1-200, no-store, no write path. 9 route auth tests + 5 service tests on in-memory SQLite. Built by Cursor auto in a detached worktree off 153a51f; Kimi review r1 FIX-THEN-COMMIT (missing route auth tests, since validation), r2 verified clean, r3 APPROVE alongside the Hermes poller consumer (mirrored in the agency-seo repo). tsc clean; vitest 1214/1214 here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
Replaces the auto-redirect home with an agency home: Sam prompt bar (sessionStorage prefill), workflow chips, missions rail (org-wide recent loop runs, deep-link selects the run), portfolio table (GSC last-28d when connected, tracked keywords, loops active, setup pills). Org-scoped server functions behind auth middleware; honest not-measured states. Built by Cursor auto; Kimi review APPROVE (tenant isolation pinned in SQL tests). 1224 tests green, typecheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
Jon: the login page should never ask. With one IdP and 730h sessions, Access now redirects straight through; when the Cloudflare session is alive the flow is fully silent. Kimi micro-review APPROVE (no change to the allow-policy, session model, or /api/internal bypass scoping). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
…t (P10) Grok build in a worktree, Kimi adversarial review: round-1 FIX (5 loophole findings: self-supplied targets, SERP-fabrication path, undefined spend gate, read-aloud ceremony, unlabeled business-fit factor) — all repaired, round-2 APPROVE. On-demand skills only: no auto-seeded loop template (monthly content loop token cost is Jon's call), no publishing path, no new storage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
Both Grok-built, Kimi K3 adversarial review APPROVE round 1. page-pruning: prune/noindex/merge candidates, recommends only, no GSC -> keep-watch cap. brand-facts: canonical brand record with provenance tags; llms.txt + JSON-LD drafts from confirmed facts only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
Map -> brief -> draft chain as a seeded monthly custom loop; seeder now honors template sourceType/customPrompt; honest skillName typing surfaced and fixed three null-unsafe UI consumption sites in SamLoopsPage. Grok-built; Kimi r1 FIX (as-never typing lie) -> repair exposed latent UI nulls -> r2 APPROVE. Tests + full tsc clean. Jon approved the monthly token cost 2026-08-31. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QruuTUXfQXZYnL5igfw9fH
Box-pushed artifacts (alert cycles, monthly reports, digests) now land in OpenSEO: POST /api/internal/agency-ops-artifacts (bearer, dedup by kind+sourceKey), agency home alerts card, Operations page with sandboxed HTML/markdown rendering. SamLoopsPage reports now render as markdown.
… severity, honest error states Post-review fixes: parse the box's real snake_case alert JSON (with camelCase fallback), treat high/critical case-insensitively, allow null domains on site-wide alerts, reject array roots as parse errors, ungate the home alerts query from projects, add real error/not-found states on the Operations page, count high alerts beyond the display cap, and test ingest validation against the real service.
…error state, count summing, conflict-lookup guard Non-validation ingest failures now return 500 ingest_failed (never the internal message, never a 400 the pusher would treat as permanent); the home alerts card gets an honest error state; lowercased severity counts sum instead of overwriting; insertIfNew guards the empty conflict lookup.
…hecks, MCP tools, project page Builder: cursor composer. Lead fixes: regenerated routeTree for the new ai-visibility route, narrowed prompt-result union before brandMentioned, widened the prompt-explorer model set lookup to accept platform strings.
Rotating suggested asks in the prompt bar, favicon/letter-tile avatars, status + setup pills from real fields only, merged honest Traffic column (no time series fetched, so no sparkline — never fabricate), missions rail edge fades + scroll buttons, shared pill tones, drill-in rows.
…letter tiles, muted contrast, quiet-state dashes Post-review fixes: pills use solid daisyUI color + -content text (light theme AA), invisible scroll buttons get pointer-events-none until revealed (hover or keyboard focus), letter tiles at L32% for white text, muted tone at /70, setup pills keep the em-dash quiet marker, scroll state rebinds via MutationObserver instead of every parent render.
… costNote honesty, labeled trend numbers
…d-operable rows, solid info pill, focused placeholder The useMemo sat after five early returns (conditional hook call — crash on error-then-recover renders). Rows get tabIndex/role/Enter+Space and a visible focus state. info tone goes solid like the others. The prompt input keeps a static placeholder while focused so the field is never blank; the rotating overlay still owns the unfocused state.
…p role=link so the nested connect link keeps its semantics
…isolation, deterministic cap self-repair, ISO cutoffs, 1h failure backoff, measured-only denominators, honest cost labels
…ess entirely, propagate reclaimed outcome, CAS the failure backoff
…rom the deployment's users in cloudflare_access mode Proven live: POST /api/internal/audits answered 409 no_actor_available and POST /api/internal/gsc|ga4 answered property_not_visible reason no_grant, because the routes looked for member rows of "shared-workspace" — the workspace merge moved every project there but cascaded the legacy orgs' member rows away. In cloudflare_access mode the deployment is one tenant: the actor is the earliest user with a non-empty email; grant holders are all users (email not required), same ordering. local_noauth keeps the member path; hosted stays refused; project ownership checks unchanged. Builder: Grok 4.6 (worktree off 5032b04). Review: Cursor auto = Composer 2.5, r1 FINDINGS (null-safe email, zero-users 409, blank-email tests) -> repair -> r2 APPROVE. Gates: tsc 0, targeted 162+. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK3iKtUGinxgMnUrxpxjbr
…loudflare_access mode Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK3iKtUGinxgMnUrxpxjbr
… requested property Explicit propertyId + name mismatch + flag → attach with a warn line and displayNameMismatchAccepted in the response; without the flag the 409 is unchanged; auto-pick ignores the flag. 4 tests. Built by Grok 4.6, reviewed by Cursor auto (Composer): APPROVE, no HIGH. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK3iKtUGinxgMnUrxpxjbr
…ernal GA4 door (Grok build, Composer review APPROVE) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK3iKtUGinxgMnUrxpxjbr
…RKER_CPU_LIMIT=off) Wix audits failed with cpu_limit on the 30 s plan default in cloudflare_access mode. Composer review APPROVE (one HIGH about free-plan self-hosts in the wild, not this deploy). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK3iKtUGinxgMnUrxpxjbr
…t-out WORKER_CPU_LIMIT=off)" This reverts commit dc6ccbe.
…pt-out WORKER_CPU_LIMIT=off)" This reverts commit a5347be.
… GET /api/internal/agency-monthly-export reader, rankSummary + GSC window fields on score-inputs Composer 2.5 build + 2 repair rounds; native Kimi K3 binding review r4 APPROVE (r3 gate evidence corrected). Gates: vitest 1575, tsc 0, vite build 0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCD7JKhqdBcUHVj3gNnZDa
….1000, default 40) — scheduler, service, trigger 429 path; env.d.ts + alchemy binding; tests (cherry-picked from build-loop-cap-20260902 commit 9d7e300; previously deployed 2026-09-02 and reverted accidentally by the 2026-09-03 fixkeys deploy — restoring) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…'already applied by the pixel', per path) — loops stop re-proposing applied fixes served_fix_keys/served_fix_paths flow from the agency board metrics pixel slice into the tool text + structuredContent; fail-closed when per-path detail is unavailable. Hermes side (seo_dashboard_export.py + agency_dash_push.py) shipped separately. Reviewed: Cursor auto r3 APPROVE 2026-09-03; combo review with 9d7e300 APPROVE.
…ities (monthly) templates; deterministic per-project schedule spread Three new client-safe loops (prompts enforce: two read-only, one title+description pending-only). One unified spread rule shared by app and migration: weekly -> assigned weekday (fnv1a(projectId:loop)%7), monthly -> day 1+hash%28, on seed and every advance; daily untouched. Kills the end-of-month cliff (~250 runs/day -> <=18/day). Includes one-off D1 stagger script (idempotent, --dry-run/--verify; ran 2026-09-03: 117 inserts + 335 updates, VERIFY OK). Reviewed: Cursor auto r3 APPROVE 2026-09-03.
…-run call caps get_business_profile/get_business_reviews join LOOP_ALLOWED_TOOLS so the GBP loops can fetch; LOOP_TOOL_CALL_CAPS + capLoopToolCalls hard-cap each at 5 calls/run (6th throws) so prompt text is never the cost control. Reviewed: Cursor auto r2 APPROVE 2026-09-03.
- Per-loop tool scoping keyed by template identity (prompt byte-match, fail-closed): write + paid GBP tools only for the templates that own them; drift-tolerant capabilities map; warn when a template-named loop misses the map; dead skillName param dropped - capLoopToolCalls fails closed when a capped tool has no callable execute; caps pinned in tests (12/12) - Reserved template prompts rejected on create AND on prompt change, with template-family carve-out and repair-path message - computeNextSamLoopRunAt: unparseable anchor throws labeled error; monthly(36)/weekly(520) bounded roll guards with shared needsRoll and loud throws on exhaustion/Date-overflow - updateSamLoop seeds use existing.projectId + final name on cadence re-anchor and enable paths - Tests: guard exhaustion (30y anchors), routine monthly advance, update-path suite, cap pins, cross-check (non-empty prompts, collision pin, full key-set equality), DOGFOOD pin+coupling Review: Opus 5 via OpenRouter r7 APPROVE (r1/r3-r6 FIX rounds resolved). Gates: tsc --noEmit clean; vitest 176 files / 1631 tests.
…loops beyond house domains Preserved uncommitted work from the main checkout before the branch fast-forwards to 5872164. Not reviewed yet — do not deploy from this.
…d house domains Peer work preserved from the main checkout's uncommitted state (15b5a13). Clean 3-way merge (verified via merge-tree). Reviewed by Opus before push.
…es TS2322 from the peer WIP; matches alchemy.run.ts idiom)
…dening - alchemy.access: service-token policy attaches ONLY to the path-scoped /mcp app, never the hostname-wide app (there it minted user-audience JWTs for service tokens — the C1 hole); annotate mcpPolicyAud - cloudflareAccess: kind no longer follows audience alone — service_token requires common_name; common_name at the user audience is rejected - transport: accessContext explicitly nullable (omitting it is now a type error); server + test call sites updated - runHeadlessSamLoop: report instruction no longer names the domains it suppresses - tests: cloudflareAccess cross-audience suite (both directions, jose claim-shape pin, user-door guard, config-missing paths) - scripts/sam-loop-prompt-refresh-20260904.py: idempotent D1 migration to byte-match stored seeded prompts to the updated templates (operator runs at deploy time; dry-run/--write/--verify like the stagger script)
Headless runs already pass isSamLoopProjectAllowed. Skill bodies were still telling the model to stop unless the domain was house-only, so enabled clients spent money and quit. Drop that stop. Composer APPROVE r3.
…ve the /mcp boundary - alchemy.access: new mcpDiscoveryBypass — Bypass(everyone) path-scoped Access app for /.well-known/oauth-authorization-server + oauth-protected-resource (public RFC 8414 metadata; machine clients and user agents both reach it; the /mcp service-token gate is untouched and never attaches hostname-wide). Docblock now describes the real design - alchemy.run: wire mcpDiscoveryBypass; mcpPolicyAud stays undefined when unprovisioned (binding omitted, visibly off — no empty-string AUD) - server.test.ts (new): the /mcp security boundary — service token goes to the OAuth provider (its 401 is the client's answer), user gate goes to the user handler with context, OPTIONS passes with explicit null, discovery paths route to the provider with the /mcp-suffix rewrite; compile-time assertion that Env carries OAUTH_KV - runHeadlessSamLoop gate early-return coverage already existed; the samSkills dead assertion removed - migration script: ASCII guard on the SUBSTR offset, cross-reference note for the customized-heuristic literals - remove committed .pyc, gitignore __pycache__
…pg client across JWKS - shared SELFHOST_OAUTH_DISCOVERY_PATH_PREFIXES (src/shared) drives BOTH the Access bypass destinations (alchemy.access) and the Worker allowlist/deny (oauth-resource/server) — the two lists cannot drift - Worker 404s anything under the discovery prefixes that is not an exact discovery path (edge bypass is prefix-matched; the Worker allowlist is exact — the edge must never admit more than the Worker serves) + test - resolveCloudflareAccessMcpGate is now network-only (verified identity, no DB); the workspace context is resolved by callers in their own short withPgClient scope AFTER the network wait; fetch() bypasses the request-wide pg wrapper for the MCP surface — a pooled client is never held across a JWKS round-trip - alchemy.access.test.ts: topology test pinning the C1 invariant (the service-token policy attaches ONLY to the /mcp app, never the hostname-wide user gate) - joseContract.test.ts: pins the REAL jose error shape (mock-free) - loop instruction drops the affirmative gate claim (silence is correct) - migration script: --verify fails on empty target match, CF_ACCOUNT_ID / D1_DATABASE_ID overrides + target printed, clearer empty-report wording - Env OAUTH_KV compile-time assertion moved beside the casts it protects - alchemy.run: note that the manual TEAM_DOMAIN+POLICY_AUD path never provisions MCP service auth
Awaiting PostHog shutdown in the finalize step could wedge the workflow after snapshots were already written, leaving status=running so the API hid positions. Flip DB status first without awaiting telemetry, reclaim snapshot-complete blockers as completed, and add a cron watchdog. Co-authored-by: Cursor <cursoragent@cursor.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7b0eb18. Configure here.
| console.log( | ||
| `[rank-check] watchdog failed stale incomplete run ${run.id}`, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Watchdog fails in-progress rank checks
High Severity
reconcileStuckRankCheckRuns marks a run failed after 25 minutes without checking whether the Cloudflare workflow is still queued or collecting. Scheduled checks sleep ~15 minutes, then run collect and live-fallback steps that often push past that window. Finalize then no-ops on a terminal run, so paid snapshots stay hidden behind the completed-run filter.
Reviewed by Cursor Bugbot for commit 7b0eb18. Configure here.
| @@ -212,7 +213,15 @@ export async function beginRankCheckRun(input: { | |||
| ageMs: Date.now() - new Date(blocker.startedAt).getTime(), | |||
| }); | |||
| if (staleReason) { | |||
| await failRunIfActive(blocker.id, staleReason, blocker); | |||
There was a problem hiding this comment.
Watchdog can clobber completed runs
High Severity
The watchdog passes its stale in-memory run into failRunIfActive, which trusts that snapshot and issues an unconditional updateRun. If the workflow completes between the coverage check and the fail write, a completed run is overwritten to failed and positions disappear again.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7b0eb18. Configure here.
| if (input.requireFullCoverage) { | ||
| if (keywordsChecked === 0 || keywordsChecked < keywordsTotal) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Full coverage ignores missing devices
High Severity
Watchdog requireFullCoverage treats distinct trackingKeywordId as done, not keyword×device tasks. With default devices=both, one device back for every keyword looks complete while the other device is still polling. The run is closed after the 3-minute grace, the inflight slot is freed, and a second paid check can start.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7b0eb18. Configure here.
|
PR hygiene (Pass 4): this branch is ~78 commits ahead of `main` (agency platform WIP ancestry). For a trust-merge of only the rank finalize hang fix, use the slim PR instead: Same tip commit intent ( |
There was a problem hiding this comment.
Agentic security review of this PR found three high-severity authorization issues: unscoped MCP OTTO/ops tools, org-wide Operations reads for any logged-in user, and new Hermes export routes that skip the hosted-mode refuse used by sibling internal APIs.
Sent by Cursor Security Agent: Security Reviewer (1)
| rationale?: string; | ||
| human_review?: string[]; | ||
| }, | ||
| _context: ToolContext, |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
propose_homegrown_otto_fixes and list_homegrown_otto_proposals discard ToolContext and read/write the global KV index (homegrown-otto:proposal-index) with no organization or project check. Sibling MCP tools (get_agency_score_inputs, withMcpProjectAuth writers) bind to the caller’s org. get_niceseo_ops_status has the same _context discard and, when configured, uses the deployment AGENCY_DASH_TOKEN for a caller-chosen hostname. These tools are registered on the shared hosted OAuth MCP server.
Impact: Any authenticated MCP or SAM session can list other tenants’ queued OTTO proposals or enqueue proposals for arbitrary domains, and can pull agency pixel/ops data using a service credential.
Reviewed by Cursor Security Reviewer for commit 7b0eb18. Configure here.
|
|
||
| export const getLatestAlertCycle = createServerFn({ method: "POST" }) | ||
| .middleware(requireAuthenticatedContext) | ||
| .handler(async () => { |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
getLatestAlertCycle, listOpsArtifacts, and getOpsArtifact only require a logged-in user. They never filter by organizationId. The handlers comment that artifacts are box-wide for a single-agency self-host, but that is not enforced (AUTH_MODE=hosted is not refused). /operations is in the default Agency sidebar for every install.
Impact: On a hosted multi-tenant deployment, any authenticated user can list and read Hermes-ingested client reports, alert cycles, and HTML artifacts for every organization.
Reviewed by Cursor Security Reviewer for commit 7b0eb18. Configure here.
| ); | ||
| } | ||
|
|
||
| const data = await getAgencyScoreInputsGlobal(domain); |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
This route authenticates only with the deployment-wide AGENCY_SCORE_EXPORT_TOKEN, then calls getAgencyScoreInputsGlobal, which scans every non-archived project (organizationId: null). Neighboring internal routes (/api/internal/projects, gsc, ga4, audits) explicitly refuse AUTH_MODE=hosted because a deployment-wide token cannot map to one SaaS org. The new Hermes routes (agency-score-inputs, agency-otto-page-inputs, agency-loop-reports, and related mutate/list endpoints) omit that refuse.
Impact: If the export token is set on hosted OpenSEO, that single secret can read (and on sibling new routes, mutate) other customers’ rank, audit, GSC, GA4, and loop data.
Reviewed by Cursor Security Reviewer for commit 7b0eb18. Configure here.




Summary
status=runningafter DFS snapshots are written.reconcileStuckRankCheckRuns) so stuck finals can complete from snapshots.7b0eb18. Do not deploy without Jon yes.Important
origin/main(peer WIP / agency platform ancestry). Review scope carefully before any merge/deploy to production.Test plan
runningfinals when snapshots existMade with Cursor